﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using Kaiser.Extensions;
using Kaiser.Infrastructure.User;

namespace Kaiser.Models
{
    public class User : UserBasic, IUser
    {
        public User()
        {
        }

        public User(string username, string displayName, string email, string password, UserStatus status,
                    UserGroupBasic userGroup)
        {
            Identity = new UserIdentity(null, false, username);
            UserID = 0;
            UserName = username;
          //  UserGroup = userGroup;
            DisplayName = displayName;
            Email = email;
            Password = password;
            Status = status;
            AuthenticationValues = new Dictionary<string, object>();

            Roles = Enumerable.Empty<RoleBasic>();
            UserGroupRoles = Enumerable.Empty<RoleBasic>();
            UserGroupRolePermissions = Enumerable.Empty<PermissionBasic>();
            RolePermissions = Enumerable.Empty<PermissionBasic>();
            Permissions = Enumerable.Empty<PermissionBasic>();
        }

        public User(int userID, string username, string displayName, string email, string password, UserStatus status,
                    UserGroupBasic userGroup)
            : this(username, displayName, email, password, status, userGroup)
        {
            Identity = new UserIdentity(null, true, username);
            UserID = userID;
        }

        public User(int userID, string username, string displayName, string email, string password, UserStatus status,
                    UserGroupBasic userGroup, DateTime creationDate
                    , IEnumerable<RoleBasic> userGroupRoles
                    , IEnumerable<RoleBasic> userRoles
                    , IEnumerable<PermissionBasic> userGroupRolePermissions
                    , IEnumerable<PermissionBasic> rolePermissions
                    , IEnumerable<PermissionBasic> userPermissions)
            : this(userID, username, displayName, email, password, status, userGroup)
        {
            CreationDate = creationDate;
            Roles = userRoles;
            UserGroupRoles = userGroupRoles;
            UserGroupRolePermissions = userGroupRolePermissions;
            RolePermissions = rolePermissions;
            Permissions = userPermissions;
        }

        /// <summary>
        ///     用户拥有的特定角色
        /// </summary>
        public virtual IEnumerable<RoleBasic> Roles { get; set; }

        /// <summary>
        ///     用户拥有的特定权限
        /// </summary>
        public virtual IEnumerable<PermissionBasic> Permissions { get; set; }

        /// <summary>
        ///     用户所属用户组所拥有的角色
        /// </summary>
        public virtual IEnumerable<RoleBasic> UserGroupRoles { get; set; }

        /// <summary>
        ///     用户所属用户组所拥有的角色所拥有的权限
        /// </summary>
        public virtual IEnumerable<PermissionBasic> UserGroupRolePermissions { get; set; }

        /// <summary>
        ///     用户拥有的角色所拥有的权限
        /// </summary>
        public virtual IEnumerable<PermissionBasic> RolePermissions { get; set; }

        #region IUser Members

        public bool IsAuthenticated
        {
            get { return Identity.IsAuthenticated; }
        }

        public string Name
        {
            get { return Identity.Name; }
        }

        public IDictionary<string, object> AuthenticationValues { get; private set; }

        public bool IsInUserGroup(string userGroupName)
        {
            return false;
        }

        public bool HasPermission(string permissionName)
        {
            return hasPermission(permissionName, Permissions)
                   || hasPermission(permissionName, UserGroupRolePermissions)
                   || hasPermission(permissionName, RolePermissions);
        }

        public bool HasPermission(Guid permissionID)
        {
            return hasPermission(permissionID, Permissions)
                   || hasPermission(permissionID, UserGroupRolePermissions)
                   || hasPermission(permissionID, RolePermissions);
        }

        public T Cast<T>() where T : class, IUser
        {
            return this as T;
        }

        #endregion

        #region IPrincipal Members

        public IIdentity Identity { get; set; }

        public bool IsInRole(string role)
        {
            return isInRole(role, Roles) || isInRole(role, UserGroupRoles);
        }

        #endregion

        #region Private Static Methods

        private static bool hasPermission(string permissionName, IEnumerable<PermissionBasic> permissions)
        {
            if (String.IsNullOrEmpty(permissionName)) return true;
            if (permissions == null || permissions.Count() == 0) return false;

            foreach (PermissionBasic permission in permissions)
                if (string.Compare(permission.PermissionName, permissionName, true) == 0)
                    return true;

            return false;
        }

        private static bool hasPermission(Guid permissionID, IEnumerable<PermissionBasic> permissions)
        {
            if (permissionID == Guid.Empty) return true;
            if (permissions == null || permissions.Count() == 0) return false;

            foreach (PermissionBasic permission in permissions)
                if (permission.PermissionID == permissionID)
                    return true;

            return false;
        }

        private static bool isInRole(string roleName, IEnumerable<RoleBasic> roles)
        {
            if (roleName.IsNullOrEmpty()) return true;
            if (roles.IsNullOrEmpty()) return false;

            foreach (RoleBasic role in roles)
                if (string.Compare(role.RoleName, roleName, true) == 0)
                    return true;

            return false;
        }

        #endregion
    }
}